"""
USB Server Python绑定
封装USB Server的C接口函数
"""

import ctypes
from typing import List, Optional, Tuple
from enum import IntEnum


class DeviceType(IntEnum):
    """设备类型枚举"""
    DeviceType_DAQ217 = 0
    DeviceType_DAQ216 = 1
    DeviceType_DAQ207 = 2
    DeviceType_DAQ206 = 3
    DeviceType_DAQ125 = 4
    DeviceType_DAQ322 = 5


class USBServerBinding:
    """USB Server Python绑定类"""
    
    def __init__(self, dll_path: str):
        """
        初始化USB Server绑定
        
        Args:
            dll_path: DLL文件路径
        """
        self.dll = ctypes.CDLL(dll_path)
        self._setup_function_signatures()
    
    def _setup_function_signatures(self):
        """设置函数签名"""
        # USBServer_New
        self.dll.USBServer_New.argtypes = [ctypes.c_uint32]
        self.dll.USBServer_New.restype = ctypes.POINTER(ctypes.c_uint32)
        
        # USBServer_Delete
        self.dll.USBServer_Delete.argtypes = [ctypes.POINTER(ctypes.c_uint32)]
        self.dll.USBServer_Delete.restype = None
        
        # USBServer_StartSearch
        self.dll.USBServer_StartSearch.argtypes = [ctypes.POINTER(ctypes.c_uint32)]
        self.dll.USBServer_StartSearch.restype = None
        
        # USBServer_GetBusNumbers
        self.dll.USBServer_GetBusNumbers.argtypes = [
            ctypes.POINTER(ctypes.c_uint32),
            ctypes.POINTER(ctypes.c_uint8)
        ]
        self.dll.USBServer_GetBusNumbers.restype = ctypes.POINTER(ctypes.c_uint32)
        
        # USBServer_GetDeviceAddresses
        self.dll.USBServer_GetDeviceAddresses.argtypes = [
            ctypes.POINTER(ctypes.c_uint32),
            ctypes.c_uint8,
            ctypes.POINTER(ctypes.c_uint8)
        ]
        self.dll.USBServer_GetDeviceAddresses.restype = ctypes.POINTER(ctypes.c_uint32)
        
        # USBServer_GetClient
        self.dll.USBServer_GetClient.argtypes = [
            ctypes.POINTER(ctypes.c_uint32),
            ctypes.c_uint8,
            ctypes.c_uint8
        ]
        self.dll.USBServer_GetClient.restype = ctypes.POINTER(ctypes.c_uint32)
        
        # USBServer_GetClientByIndex
        self.dll.USBServer_GetClientByIndex.argtypes = [
            ctypes.POINTER(ctypes.c_uint32),
            ctypes.c_uint32
        ]
        self.dll.USBServer_GetClientByIndex.restype = ctypes.POINTER(ctypes.c_uint32)
        
        # USBServer_GetDeviceCount
        self.dll.USBServer_GetDeviceCount.argtypes = [ctypes.POINTER(ctypes.c_uint32)]
        self.dll.USBServer_GetDeviceCount.restype = ctypes.c_uint32
    
    def create_server(self, device_type: DeviceType) -> Optional[ctypes.POINTER(ctypes.c_uint32)]:
        """
        创建USB服务器实例
        
        Args:
            device_type: 设备类型
            
        Returns:
            USB服务器句柄，失败返回None
        """
        handle = self.dll.USBServer_New(ctypes.c_uint32(device_type.value))
        return handle if handle else None
    
    def delete_server(self, handle: ctypes.POINTER(ctypes.c_uint32)) -> None:
        """
        删除USB服务器实例
        
        Args:
            handle: USB服务器句柄
        """
        if handle:
            self.dll.USBServer_Delete(handle)
    
    def start_search(self, handle: ctypes.POINTER(ctypes.c_uint32)) -> None:
        """
        开始搜索设备
        
        Args:
            handle: USB服务器句柄
        """
        if handle:
            self.dll.USBServer_StartSearch(handle)
    
    def get_bus_numbers(self, handle: ctypes.POINTER(ctypes.c_uint32)) -> List[int]:
        """
        获取总线号列表
        
        Args:
            handle: USB服务器句柄
            
        Returns:
            总线号列表
        """
        if not handle:
            return []
        
        bus_count = ctypes.c_uint8()
        bus_numbers_ptr = self.dll.USBServer_GetBusNumbers(handle, ctypes.byref(bus_count))
        
        if not bus_numbers_ptr or bus_count.value == 0:
            return []
        
        # 将C数组转换为Python列表
        bus_numbers = []
        for i in range(bus_count.value):
            bus_numbers.append(bus_numbers_ptr[i])
        
        return bus_numbers
    
    def get_device_addresses(self, handle: ctypes.POINTER(ctypes.c_uint32), 
                           bus_number: int) -> List[int]:
        """
        获取指定总线上的设备地址列表
        
        Args:
            handle: USB服务器句柄
            bus_number: 总线号
            
        Returns:
            设备地址列表
        """
        if not handle:
            return []
        
        device_count = ctypes.c_uint8()
        device_addresses_ptr = self.dll.USBServer_GetDeviceAddresses(
            handle, 
            ctypes.c_uint8(bus_number), 
            ctypes.byref(device_count)
        )
        
        if not device_addresses_ptr or device_count.value == 0:
            return []
        
        # 将C数组转换为Python列表
        device_addresses = []
        for i in range(device_count.value):
            device_addresses.append(device_addresses_ptr[i])
        
        return device_addresses
    
    def get_client(self, handle: ctypes.POINTER(ctypes.c_uint32), 
                   bus_number: int, device_address: int) -> Optional[ctypes.POINTER(ctypes.c_uint32)]:
        """
        获取指定总线和设备地址的客户端
        
        Args:
            handle: USB服务器句柄
            bus_number: 总线号
            device_address: 设备地址
            
        Returns:
            客户端句柄，失败返回None
        """
        if not handle:
            return None
        
        client_handle = self.dll.USBServer_GetClient(
            handle,
            ctypes.c_uint8(bus_number),
            ctypes.c_uint8(device_address)
        )
        
        return client_handle if client_handle else None
    
    def get_client_by_index(self, handle: ctypes.POINTER(ctypes.c_uint32), 
                           device_index: int) -> Optional[ctypes.POINTER(ctypes.c_uint32)]:
        """
        根据索引获取客户端
        
        Args:
            handle: USB服务器句柄
            device_index: 设备索引
            
        Returns:
            客户端句柄，失败返回None
        """
        if not handle:
            return None
        
        client_handle = self.dll.USBServer_GetClientByIndex(
            handle,
            ctypes.c_uint32(device_index)
        )
        
        return client_handle if client_handle else None
    
    def get_device_count(self, handle: ctypes.POINTER(ctypes.c_uint32)) -> int:
        """
        获取设备总数
        
        Args:
            handle: USB服务器句柄
            
        Returns:
            设备总数
        """
        if not handle:
            return 0
        
        return self.dll.USBServer_GetDeviceCount(handle) 